package ch.bluepenguin.jcr.groovy.tests

import javax.jcr.Session
import javax.jcr.Repository
import org.apache.jackrabbit.core.TransientRepository
import javax.jcr.SimpleCredentials
import ch.bluepenguin.jcr.groovy.builder.JcrPersister
import com.thoughtworks.xstream.XStream

class Child3{
    String c3
}

class Child1{
    String c
    Set aset
}
class Child2{
    String c2
    Calendar calendar
    def otherRef
}
class Model1 {
    String a
    Child1 b
    Child1 c
    Child1 d
    String z
    Child2 otherChild
    Set children2=[]
    List children3= []
    public static hasACertainRelationTo = [b:Child1, c:Child1]
}
class PersistanceStrategyTests extends JcrBaseTest  {
//        static Session session=null

              private XStream stream = new XStream()
    void testDoubleSaveAndLoad() {
        withPersister "testDoubleSaveAndLoad", { strategy ->
            strategy.instrumentate(Model1, "z")
            Model1 simple = new Model1(a: "prop a", z: "key")
            simple.save()
            simple.save()
            println "testDoubleSaveAndLoad/${simple.class.name}/key"

           // println stream.toXML(strategy.session.rootNode.getNode("testDoubleSaveAndLoad/${simple.class.name}/key"))
            assert strategy.session.rootNode.getNode("testDoubleSaveAndLoad/${simple.class.name}/key").
                getProperty('a').string=='prop a'
            assert simple.uuid != null
            Model1 loaded = Model1.get("key")
            assert loaded.a == simple.a
            loaded = Model1.get("key")
            assert loaded.a == simple.a

        }
    }

    void testCRUDOne() {
        withPersister "testCRUDOne", { strategy ->
            def session = strategy.session
            strategy.instrumentate(Model1, "z")
            Model1 simple = new Model1(a: "property a, but not the key!", z: "property z, is key!")
            simple.save()
            //should be same
            assert session.rootNode.getNode("testCRUDOne/${simple.class.name}/property z, is key!").
                getProperty('a').string=='property a, but not the key!'
            //should be same
            assert session.rootNode.getNode("testCRUDOne/${simple.class.name}/property z, is key!").
                getProperty('z').string=='property z, is key!'
            //should be set
            assert simple.uuid != null
            Model1 loaded = Model1.get("property z, is key!")
            assert loaded.a == simple.a

            loaded.children2 = ["test", "testagain"]
            loaded.children3 = ["test", "testagain"]
            loaded.save()
            assert session.rootNode.getNode("testCRUDOne/${simple.class.name}/property z, is key!").
                getProperty('xstream:children2').string.startsWith("<set>")
            assert session.rootNode.getNode("testCRUDOne/${simple.class.name}/property z, is key!").
                getProperty('xstream:children3').string.startsWith("<list>")

        }
    }

    void testListReference() {
        withPersister "testListReference", { strategy ->
            strategy.instrumentate(Model1, "a")
            strategy.instrumentate(Child3, "c3")
            Model1 parent = new Model1(a: "keyparent")
//            child.otherRef = parent
            parent.children3 << new Child3(c3:"c3")
            parent.save()
            Model1 parentLoaded = Model1.get("keyparent")
            assert(parentLoaded.children3[0].c3=="c3")
            println parentLoaded.dump()
        }
    }
    void testRecursion() {
        withPersister "testRecursion", { strategy ->
            strategy.instrumentate(Model1, "a")
            strategy.instrumentate(Child1, "c")
            strategy.instrumentate(Child2, "c2")
            Child2 child = new Child2(c2:"c2")
            Model1 parent = new Model1(a: "keyparent", otherChild: child)
            child.otherRef = parent
            parent.save()
            Model1 parentLoaded = Model1.get("keyparent")
            assert(parentLoaded.otherChild.c2=="c2")
            println parentLoaded.dump()

        }
    }

    void testCRUDHierarchy() {
        withPersister "testCRUDHierarchy", { strategy ->
          strategy.instrumentate(Model1, "a")
          strategy.instrumentate(Child1, "c")
          strategy.instrumentate(Child2, "c2")

          Child1 child = new Child1(c: "c", aset:["one", "two" , "three"])

          Child1 cOneOne = new Child1(c: "c1123", aset:["one", "two" , "three"])
          Child1 childB= new Child1(c: "b", aset:["one", "two" , "three"])
          Child1 childD = new Child1(c: "d", aset:["one", "two" , "three"])
          Child2 child2 = new Child2(c2:"c2")
          Model1 a = new Model1(a: "key", otherChild: child2, d: cOneOne, b: childB, c:child, children2:[childB,cOneOne, new Child1(c: "c12")])
          //recursive
          child2.otherRef = a
          a.save()
          //double save
            a.save()
          def session = strategy.session
          assert session.rootNode.getNode("testCRUDHierarchy/${a.class.name}/key").
              getProperty('a').string=='key'
          assert a.uuid != null
          assert session.rootNode.getNode("testCRUDHierarchy/${child.class.name}/c").
              getProperty('c').string=='c'
          assert child.uuid != null

          Child1 loaded = Child1.get("c")
          Model1 parentLoaded = Model1.get("key")
          assert parentLoaded.otherChild.otherRef.a == parentLoaded.a
            int i=0
        }

    }
}